//====================================<4> 基础回顾 js异步编程的 4 种方法===================================================
// 这只是异步编程，并不是异步执行，javascript是单线程的，
//即使使用了异步编程，在执行层面也是一步一步执行的，只是会随时有插队的而已

//异步编程的关键是切分任务，并且保证每个任务足够小，
//执行的足够快。注意，任务能被快速执行是关键中的关键。因为在单线程
//环境中，只要有一个任务的执行时间稍长，就会导致排在后面的任务被延后。
//js的异步更多是为了和界面UI分时，故尽量将任务切割为细粒度的小任务，每次执行完小任务，然后让时间给UI
//这样UI就不会卡死，若任务切割的不好，任务将耗时长，无论什么招，一样卡死UI，因为JS的异步是想不了真正并行，只是插队而已
//JS 是单线程的，异步也不会加快程序运行

//回调函数不一定是异步的，@@异步会有暴露过多接口的问题

//异步有伪异步， 真正的异步是程序执行期间不会冻结UI的，比如AJAX操作

//底层 的多线程，才是所谓的异步; ajax()是底层多线程函数

//setTimeout是一个异步方法，推迟执行，改变队列顺序而已。

//——————》js无论怎么做都 是单线程的，异步也不能开启多线程，
//JS里的异步只是改变队列的执行顺序而已，要想不出现耗时代码，
//唯一的方法就是把耗时代码切成小段的代码，然后用setTimeout异步留出线程的空闲
//时间给渲染线程，这样才不会出现UI卡死的现象;

//----------- 异步编程方法 一：回调函数


function f1(){
	alert(1);
};
function f2(){
	alert(2);
};
//同步执行
f1();
f2();
//异步执行 回调 若f1耗时，把f2改写成f1的回调
//采用setTimeout这种方式，虽然我们把同步操作，变成了异步操作，f1不会阻塞程序运行，先执行程序的主要逻辑，将耗时的操作推迟执行
//回调缺点：高度耦合，流程混乱，每个任务只能指定一个回调函数
function f1(callback){
	setTimeout(function(){
		//f1的代码
		alert(1);
		callback();
	},5000);
};
f1(f2);
//----------- 异步编程方法 二：事件监听["信号"] （ 事件驱动模式 ）
	
// 任务的执行不取决于代码的顺序，而取决于某个事件是否发生
f1.on("done",f2);
//-----------------
function f1(){
	setTimeout(function(){
		//f1的代码
		f1.trigger("done");
	},1000)
};
//当f1的代码执行完，触发done，再执行f2;

//优点：可以去耦合，可以绑定多个事件，每个事件可以有多个回调
// 有利于实现模块化，缺点：整个程序都变成事件驱动型，运行流程会不清晰


//----------- 异步编程方法 三：发布/订阅

//我们假设存在一个 “信号中心”，某个任务执行完成，就向信号中心“发布”（publish）
//一个信号，其他任务可以向信号中心“订阅”（subscribe）这个信号，从而知道什么时候
//自己可以开始执行;——》"发布/订阅模式"（publish-subscribe pattern）,又叫"观察者模式"（observer pattern）
// 这个模式有多种实现， 例如 Ben Alman的Tiny Pub/Sub

// 这种方法的性质与"事件监听"类似，优于事件监听，
//因 我们可以通过查看"消息中心"，了解存在多少信号，
//每个信号有多少 订阅者，从而监控程序的运行。

//首先，f2向"信号中心"jQuery订阅"done"信号。
//　　jQuery.subscribe("done", f2);
//然后，f1进行如下改写：
//　　function f1(){
//　　　　setTimeout(function () {
//　　　　　　// f1的任务代码
//　　　　　　jQuery.publish("done");
//　　　　}, 1000);
//　　}

//----------- 异步编程方法 四：Promises对象

//promises对象是CommonJs工作组提出的一种规范，目的是为异步编程提供统一接口
//每一个异步任务返回一个Promises对象，该对象有一个then方法，允许制定回调函数;

//f1().then(f2);
//f1要进行如下改写（这里使用的是jQuery的实现）：
//　　function f1(){
//　　　　var dfd = $.Deferred();
//　　　　setTimeout(function () {
//　　　　　　// f1的任务代码
//　　　　　　dfd.resolve();
//　　　　}, 500);
//　　　　return dfd.promise;
//　　}
//这样写的优点在于，回调函数变成了链式写法，程序的流程可以看得很清楚，而且有一整套的配套方法，可以实现许多强大的功能。
//比如，指定多个回调函数：
//　　f1().then(f2).then(f3);
//再比如，指定发生错误时的回调函数：
//　　f1().then(f2).fail(f3);
//而且，它还有一个前面三种方法都没有的好处：如果一个任务已经完成，再添加回调函数，该回调函数会立即执行。所以，你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解，都相对比较难。




//=======================================================================================
// <3>
var i = 0; var j = i+++i+++i++;

//---------
var a = 2;
a = a.z = 2;

//a.z //undefined;


// <1>
//javascript 连等赋值问题
var a = {n:1};  
var b = a; // 持有a，以回查  
a.x = a = {n:2};  
alert(a.x);// --> undefined  
alert(b.x);// --> {n:2}

//  事实上，解析器在接受到 a = a.x = {n:2} 这样的语句后，会这样做：
//  
//  找到 a 和 a.x 的指针。如果已有指针，那么不改变它。如果没有指针，即那个变量还没被申明，那么就创建它，指向 null。
//  a 是有指针的，指向 {n:1}；a.x 是没有指针的，所以创建它，指向 null。
//  然后把上面找到的指针，都指向最右侧赋的那个值，即 {n:2}。

//javascript 连等赋值问题
var x = 1;
x.y  = x = { v : 777 };
console.log(x.y);
//x是有指针的，指向 { v : 777 };  x.y是没有指针的，所以创建它，指向null.


// <2> deferred对象有三种执行状态----未完成，已完成和已失败。
//开发网站的过程中，我们经常遇到某些耗时很长的javascript操作。其中，既有异步的操作（比如ajax读取服务器数据），也有同步的操作（比如遍历一个大型数组），它们都不是立即能得到结果的。
//通常的做法是，为它们指定回调函数（callback）。即事先规定，一旦它们运行结束，应该调用哪些函数。
//但是，在回调函数方面，jQuery的功能非常弱。为了改变这一点，jQuery开发团队就设计了deferred对象。
//简单说，deferred对象就是jQuery的回调函数解决方案。在英语中，defer的意思是"延迟"，所以deferred对象的含义就是"延迟"到未来某个点再执行。
//它解决了如何处理耗时操作的问题，对那些操作提供了更好的控制，以及统一的编程接口。
//$.when($.ajax("test1.html"), $.ajax("test2.html"))
//　　.done(function(){ alert("哈哈，成功了！"); })
//　　.fail(function(){ alert("出错啦！"); });



//　$.ajax("test.html")
//　　.done(function(){ alert("哈哈，成功了！");} )
//　　.fail(function(){ alert("出错啦！"); } )
//　　.done(function(){ alert("第二个回调函数！");} );


